﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ControlsLib.Controls
{
    /// <summary>
    /// This class automates cross thread operations.
    /// </summary>
    /// <example>
    /// The usage is very straight forward. If we have a method without arguments and without return value, 
    /// only the method name needs to be specified. Everything else is done by the C# compiler.
    /// 
    /// theControl.Invoke(MethodTomodifyUI);
    /// theControl.Invoke(()=>theControl.Text=sender.Name+" "+ telegram.Id);
    /// 
    /// If we have an argument for the internally called method (or methods) we need to use the delegate keyword:
    /// int value = 10;
    /// theControl.Invoke(delegate { UpdateControls(value); });
    ///
    /// And if we expect some return value, we need to use the Invoke method that expect a generic argument.
    /// int value = 10;
    /// int result = theControl.Invoke<int>(delegate { return UpdateControls(value); });
    /// </example>
    /// <remarks>
    /// http://www.liensberger.it/web/blog/?p=90
    /// </remarks>
    public static class ControlHelper
    {
        public delegate void Func();
        public delegate TResult Func<TResult>();

        /// <summary>
        /// Invokes a cross-thread operation that doesn’t return a result.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="del"></param>
        public static void Invoke(this Control control, Func del)
        {
            if (control == null)
                throw new ArgumentNullException("control");
            if (del == null)
                throw new ArgumentNullException("del");

            // Check if we need to use the controls invoke method to do cross-thread operations.
            if (control.InvokeRequired)
                control.Invoke(del);
            else
                del();
        }

        /// <summary>
        /// Invokes a cross-thread operation that returns a result.
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="control"></param>
        /// <param name="del"></param>
        /// <returns></returns>
        public static TResult Invoke<TResult>(this Control control, Func<TResult> del)
        {
            if (control == null)
                throw new ArgumentNullException("control");
            if (del == null)
                throw new ArgumentNullException("del");

            // Check if we need to use the controls invoke method to do cross-thread operations.
            if (control.InvokeRequired)
                return (TResult)control.Invoke(del);
            return del();
        }
    }

}
